home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / Utilities / Catharsis / Catharsis.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-07-04  |  20.8 KB  |  797 lines

  1. /*
  2.     Catharsis (v1.0p)
  3.     Alpha release (p = in progress).
  4.  
  5.     An  Amiga  shared  library  to  modify  ugly  looking  fonts  by  attaching  a  second,  modified
  6.     character-bitmap where some pixels may be added or will be overwritten by the newly created.
  7.  
  8.     Status/Copyright:    PUBLIC DOMAIN SOFTWARE
  9.     Author:    Joerg van de Loo    email: Joergloo@aol.com        (<- case sensitive)
  10.  
  11.     By the way:
  12.         This  is  an  experimental  attempt  written  by  J.v.d.Loo  to try to make the 'times' fonts
  13.         useable since these are the default for WEB-browsers.
  14.  
  15.     I  hope  this  library is useable and programmers modify their programs to support this library -
  16.     so that the users have the benefit of readable fonts.
  17.  
  18.     I  would  greatly  appreciate when someone will improve this library or take over the development
  19.     since I'm a bit lazy.
  20. */
  21.  
  22. #include <exec/memory.h>
  23. #include <exec/libraries.h>
  24.  
  25. #include <dos/dos.h>
  26.  
  27. #include <graphics/gfxbase.h>
  28. #include <graphics/gfx.h>
  29. #include <graphics/rastport.h>
  30. #include <graphics/text.h>
  31.  
  32. #include <intuition/intuitionbase.h>
  33.  
  34. #include <clib/exec_protos.h>
  35. #include <clib/intuition_protos.h>
  36. #include <clib/graphics_protos.h>
  37.  
  38. #include <pragma/exec_lib.h>
  39. #include <pragma/intuition_lib.h>
  40. #include <pragma/graphics_lib.h>
  41.  
  42. #if !defined(__MAXON__) && !defined(__STORM__)
  43. #include <proto/exec.h>
  44. #include <proto/intuition.h>
  45. #include <proto/graphics.h>
  46. #else
  47. #include <pragma/exec_lib.h>
  48. #include <pragma/intuition_lib.h>
  49. #include <pragma/graphics_lib.h>
  50. #endif
  51.  
  52. #ifdef __GNUC__
  53.  #define ASM
  54.  #define REG(reg,arg) arg __asm(#reg)
  55. #else
  56.  #if !defined (__MAXON__) 
  57.  #define ASM __asm
  58.  #endif
  59.  #define REG(reg,arg) register __##reg arg
  60. #endif
  61.  
  62. #ifdef __MAXON__
  63.  extern "C" void GetBaseReg( void);
  64.  #define __saveds
  65.  #define ASM
  66. #endif
  67.  
  68. #if defined(__MAXON__) || defined(__STORM__)
  69.   #define __inline
  70.   #define __stdargs
  71. #endif
  72.  
  73. extern struct GfxBase *GfxBase;
  74. extern struct IntuitionBase *IntuitionBase;
  75.  
  76.  
  77. struct SharedLib
  78. {
  79.     struct Node sl_LibNode;
  80.     UBYTE sl_Flags;                            // LIB Flags
  81.     UBYTE sl_Pad0;                            // Dummy
  82.     UWORD sl_NegSize;                        // LIB Negative size (function table)
  83.     UWORD sl_PosSize;                        // LIB Positive size (it's this table)
  84.     UWORD sl_Version;                        // LIB Version
  85.     UWORD sl_Revision;                        // LIB Revision
  86.     char *sl_IdString;                        // LIB Detail string
  87.     ULONG sl_Sum;                            // LIB Checksum
  88.     UWORD sl_OpenCnt;                        // LIB Open count
  89.     UWORD sl_PatchCnt;                        // - Internally used
  90.     BPTR sl_SegList;                        // LIB Segment pointer
  91.     void *sl_OldFuncPtr;
  92.     struct ExecBase *sl_SysBase;            // Pointers to SysBase
  93.     struct GfxBase *sl_GfxBase;
  94.     struct IntuitionBase *sl_IntuitionBase;
  95.     struct TextFont *sl_TextFont[256];        // Remembered TextFont pointers
  96.     struct TextFont *sl_CatharsisFont[256];    // Created TextFont pointers
  97. };                                            // Size of table (positive size)
  98.  
  99.  
  100. /* Type definitions */
  101.  
  102. struct CharInfo
  103. {
  104.     unsigned short offset;
  105.     unsigned short size;
  106. };
  107.  
  108. struct CharArray
  109. {
  110.     struct CharInfo CharIndex[256];        // Points to each character's CharInfo (see above)
  111. };
  112.  
  113. /* This table is used for decoding */
  114. struct    FontDescription
  115. {
  116.     struct RastPort    rport;        // For existing, encoded data of font
  117.     struct BitMap    bmap;
  118.     struct RastPort    destrp;        // For the newly, slightly changed font data
  119.     struct BitMap    destbm;
  120.  
  121.     unsigned char *data;        // Font data information pointer
  122.     unsigned short bytesperrow;    // Complete line with information for all chars
  123.  
  124.     unsigned short lowchar;        // e.g. 32
  125.     unsigned short hichar;        // e.g. 255
  126.  
  127.     unsigned short charheight;    // Height of this char
  128.     unsigned short charoffset;    // The offset in pixels to reach the information for this char in "data"
  129.     unsigned short charwidth;    // The amount of information stored per line for this char (e.g. 9)
  130. };
  131.  
  132. /*    -------------------------------------------------------------------------------------------------
  133.  
  134.     This  is  the  basic  function to modify a single character which takes a given character (namely
  135.     its  bitmap)  and  creates  a second character which pixels do not be necessarily in the original
  136.     character,  in addition, it doesn't copies pixels one to one into the second character (-bitmap).
  137.     Only  pixels which are not present in the original character will be stored in the newly created,
  138.     with  the  exception  of  pixels that have to be eleminated respectively exchanged by a different
  139.     colour to make this character better readable.
  140.  
  141.     The  newly  created  charcater  should  be rendered into the RastPort with a different colour and
  142.     draw-mode JAM1 (JAM1 = do not erase background)
  143. */
  144.  
  145. void ModifyCharacter( struct FontDescription *fd)
  146. {
  147.     register UWORD c0, c, cc, x, charX, y;    // Let the compiler choose amount of reg-vars
  148.  
  149.     x = 0;                                    // No pixel in horizontal direction of this char worked out
  150.  
  151.     while (x + 1 < fd->charwidth)            // As long some pixels left to do (at least the square should be readable)
  152.     {
  153.         y = 0;                                // We're at the top of this character
  154.  
  155.         charX = fd->charoffset + x;         // Pixel position (X) within source and destination rastport
  156.  
  157.         while (y < fd->charheight - 1)        // As long as the square can be read in
  158.         {
  159.             /* Read a square of 2*2 pixels into 'c' and
  160.                a rectangle of 3*2 pixels into 'cc'
  161.             */
  162.  
  163.             if (y == 0)                        // Only when at top of char we have to read in square's first row pixels...>
  164.             {
  165.                 c = (UWORD) ReadPixel( &fd->rport, charX, y);
  166.                 c = (c << 1);
  167.                 c |= ReadPixel( &fd->rport, charX + 1, y);
  168.                 c = (c << 1);
  169.             }
  170.             else                            // >... else we can use the existing
  171.             {
  172.                 c = ((c & 3) << 1);            // Since next row is already in 'c'
  173.             }
  174.  
  175.             if (x + 2 < fd->charwidth)        // Can the rectangle be read in?
  176.             {
  177.                 if (y == 0)                    // If we have to read in this pixel...
  178.                 {
  179.                     cc = c;
  180.                     cc |= ReadPixel( &fd->rport, charX + 2, y);    // 3rd pixel!
  181.                     cc = (cc << 1);
  182.                 }
  183.                 else
  184.                 {
  185.                     cc = ((cc & 7) << 1);    // Otherwise take the rectangle's 2nd row as 1st
  186.                 }
  187.             }
  188.  
  189.             // ------------------------------------
  190.  
  191.             c0 = ReadPixel( &fd->rport, charX, y + 1);
  192.             c |= c0;
  193.             cc |= c0;
  194.             c = (c << 1);
  195.             cc = (cc << 1);
  196.  
  197.             c0 = ReadPixel( &fd->rport, charX + 1, y + 1);
  198.             c |= c0;
  199.  
  200.             if (x + 2 < fd->charwidth)    // Can the rectangle be read in?
  201.             {
  202.                 cc |= c0;
  203.                 cc = (cc << 1);
  204.                 cc |= ReadPixel( &fd->rport, charX + 2, y + 1);    // 3rd pixel!
  205.             }
  206.             else
  207.             {
  208.                 cc = 0;
  209.             }
  210.  
  211.             /* 'c' contains a 2*2 square in binary format, e.g:
  212.                 15 = ##        8 + 4
  213.                      ##        2 + 1 = 8 + 4 + 2 + 1
  214.  
  215.                 07 = .#        0 + 4
  216.                      ##        2 + 1 = 0 + 4 + 2 + 1
  217.  
  218.                 11 = #.        8 + 0
  219.                      ##        4 + 2 = 8 + 0 + 2 + 1
  220.  
  221.                 13 = ##        8 + 4
  222.                      .#        0 + 1 = 8 + 4 + 0 + 1
  223.  
  224.                 'cc' contains a rectangle of 3*2
  225.             */
  226.  
  227.             if (y <= fd->charheight / 2)    // One pixel more than halve of character's height when scanning from top to down
  228.             {
  229.                 if (fd->charheight > 15)    // Fonts higher than 15 pixels require rectangles of 4*3 and 3*4, which isn't supported,
  230.                 {                            // where the 4*3's value 230 must be changed to 192 and 3*4's 3288 to 3272 (erasing).
  231.                     switch (c)                // Font is higher than 15 pixels and we applying pixels within an area from top to middle of char
  232.                     {
  233.                         case 9:
  234.                             WritePixel( &fd->destrp, charX, y + 1);
  235.                             break;
  236.  
  237.                         case 6:
  238.                             WritePixel( &fd->destrp, charX, y);
  239.                             break;
  240.  
  241.                         case 7:
  242.                             WritePixel( &fd->destrp, charX, y);
  243.                             break;
  244.  
  245.                         case 11:
  246.                             WritePixel( &fd->destrp, charX + 1, y);
  247.                             break;
  248.  
  249.                         case 13:
  250.                             WritePixel( &fd->destrp, charX, y + 1);
  251.                             break;
  252.  
  253.                         case 14:
  254.                             WritePixel( &fd->destrp, charX + 1, y + 1);
  255.                             break;
  256.                     }
  257.                 }
  258.                 else
  259.                 {
  260.                     switch (c)                // Font is smaller 15 pixels in height, thus apply/exchange pixels
  261.                     {
  262.                         case 9:
  263.                             WritePixel( &fd->destrp, charX, y + 1);
  264.                             break;
  265.  
  266.                         case 6:
  267.                             WritePixel( &fd->destrp, charX, y);
  268.                             break;
  269.  
  270.                         default:
  271.                             switch (cc)
  272.                             {
  273.                                 case 30:
  274.                                     WritePixel( &fd->destrp, charX + 1, y + 1);        // Displace pixels
  275.                                     break;
  276.  
  277.                                 case 51:
  278.                                     WritePixel( &fd->destrp, charX + 1, y + 1);        // Displace pixels
  279.                                     break;
  280.  
  281.                                 default:    // NOTE: Following modifiers can make the font look more ugly!
  282.                                     switch (c)
  283.                                     {
  284.                                         case 7:
  285.                                             WritePixel( &fd->destrp, charX, y);
  286.                                             break;
  287.  
  288.                                         case 13:
  289.                                             WritePixel( &fd->destrp, charX, y + 1);
  290.                                             break;
  291.                                     }
  292.                                     break;
  293.                             }        // end switch 'cc'
  294.                             break;    // break default
  295.                     
  296.                     }    // end switch 'c¹'
  297.                 } // end inner ELSE
  298.             }
  299.             else    // We are going to modify an area from the middle to the bottom of the char
  300.             {
  301.                 if (fd->charheight > 15)    // See above
  302.                 {
  303.                     switch (c)
  304.                     {
  305.                         case 9:
  306.                             WritePixel( &fd->destrp, charX, y + 1);
  307.                             break;
  308.  
  309.                         case 6:
  310.                             WritePixel( &fd->destrp, charX, y);
  311.                             break;
  312.  
  313.                         case 7:
  314.                             WritePixel( &fd->destrp, charX, y);
  315.                             break;
  316.  
  317.                         case 11:
  318.                             WritePixel( &fd->destrp, charX + 1, y);
  319.                             break;
  320.  
  321.                         case 13:
  322.                             WritePixel( &fd->destrp, charX, y + 1);
  323.                             break;
  324.  
  325.                         case 14:
  326.                             WritePixel( &fd->destrp, charX + 1, y + 1);
  327.                             break;
  328.                     }
  329.                 }
  330.                 else
  331.                 {
  332.                     switch (c)
  333.                     {
  334.                         case 9:
  335.                             WritePixel( &fd->destrp, charX, y + 1);
  336.                             break;
  337.  
  338.                         case 6:
  339.                             WritePixel( &fd->destrp, charX, y);
  340.                             break;
  341.  
  342.                         default:
  343.                             switch (cc)
  344.                             {
  345.                                 case 30:
  346.                                     WritePixel( &fd->destrp, charX + 1, y);
  347.                                     break;
  348.  
  349.                                 case 51:
  350.                                     WritePixel( &fd->destrp, charX + 1, y);
  351.                                     break;
  352.  
  353.                                 default:
  354.                                     switch (c)
  355.                                     {
  356.                                         case 7:
  357.                                             WritePixel( &fd->destrp, charX, y);
  358.                                             break;
  359.  
  360.                                         case 13:
  361.                                             WritePixel( &fd->destrp, charX, y + 1);
  362.                                             break;
  363.                                     }
  364.                                     break;
  365.                             }        // end switch 'cc'
  366.                             break;    // break default
  367.                     
  368.                     }    // end switch 'c¹'
  369.                 }
  370.             }
  371.  
  372.             y ++;    // Continue at next row
  373.         }
  374.  
  375.         x ++;    // Continue at next horizontal pixel and row zero
  376.     }
  377.  
  378. }
  379.  
  380. void ModifyCharacterA( REG(a0,struct FontDescription *fd))
  381. {
  382.     ModifyCharacter( fd);
  383. }
  384.  
  385. /* ---------------------------------------------------------------------------------- */
  386.  
  387. struct TextFont *CreateCatharsisFont( struct TextFont *font)
  388. {
  389.     struct TextFont *ctsfont;    // New font to create
  390.     struct CharArray *farray;    // Pointer to the characters specific data
  391.     unsigned short textchar;    // A simple counter
  392.     struct FontDescription *fd;    // Var-table
  393.     unsigned long memattr;        // Attribute for bitmap-allocation
  394.  
  395.     // Demand memory for faked TextFont (that one we're going to create)
  396.     ctsfont = (struct TextFont *) AllocMem( sizeof (struct TextFont), MEMF_CLEAR);
  397.     if (ctsfont == NULL)
  398.         return NULL;
  399.  
  400.     // Duplicate font-header
  401.     CopyMem( font, ctsfont, sizeof( struct TextFont));
  402.  
  403.  
  404.     // Demand memory for table of variables
  405.     fd = (struct FontDescription *) AllocMem( sizeof (struct FontDescription), MEMF_CLEAR);
  406.     if (fd == NULL)
  407.     {
  408.         FreeMem( ctsfont, sizeof (struct TextFont));
  409.         return NULL;
  410.     }
  411.  
  412.     fd->data = (unsigned char *) font->tf_CharData;        // Encoded pixels (PLANAR)
  413.     fd->bytesperrow = font->tf_Modulo;                    // Bytes in horizontal direction
  414.     fd->lowchar = font->tf_LoChar;                        // First encoded char
  415.     fd->hichar = font->tf_HiChar;                        // Last encoded char
  416.     fd->charheight = font->tf_YSize;                    // Height of all chars
  417.  
  418.     // Create a bitmap for the font we're going to use as input
  419.     fd->bmap.BytesPerRow = fd->bytesperrow;
  420.     fd->bmap.Rows = fd->charheight;
  421.     fd->bmap.Flags = BMF_STANDARD;
  422.     fd->bmap.Depth = 1;
  423.     fd->bmap.pad = NULL;
  424.     fd->bmap.Planes[0] = fd->data;
  425.  
  426.     // Set up a RastPort for the original font so we easily can use system functions to read its data
  427.     InitRastPort( &fd->rport);
  428.     fd->rport.BitMap = &fd->bmap;
  429.  
  430.     // Init a new rastport for the additional pixels (second font) so we can render...
  431.     InitRastPort( &fd->destrp);
  432.     // ...into this created bitmap
  433.     CopyMem( &fd->bmap, &fd->destbm, sizeof (struct BitMap));
  434.  
  435.  
  436.     // Figure out if the font-render data has to be placed in CHIP-Memory
  437.     memattr = MEMF_CHIP;    // Default; use PLANAR-data in CHIP-Memory
  438.     if (IntuitionBase->ActiveScreen)    // A screen opened?
  439.     {
  440.         if ( GfxBase->LibNode.lib_Version > 38)    // At least OS 3 ?
  441.         {
  442.             if ( !GetBitMapAttr( IntuitionBase->ActiveScreen->RastPort.BitMap, BMA_FLAGS) & BMF_STANDARD )
  443.                 memattr = NULL;    // Use FAST-Memory for PLANAR-data!
  444.         }
  445.     }
  446.  
  447.  
  448.     // We need one additional bitmap (which becomes TextFont->tf_CharData) to render into
  449.     fd->destbm.Planes[0] = (PLANEPTR) AllocMem( fd->bytesperrow * fd->charheight, memattr|MEMF_CLEAR);
  450.     if (!fd->destbm.Planes[0])
  451.     {
  452.         FreeMem( fd, sizeof (struct FontDescription));
  453.         FreeMem( ctsfont, sizeof (struct TextFont));
  454.         return NULL;
  455.     }
  456.  
  457.     // The TextFont-headers data pointer points to this new created bitmap
  458.     ctsfont->tf_CharData = fd->destbm.Planes[0];
  459.     fd->destrp.BitMap = &fd->destbm;
  460.  
  461.     farray = (struct CharArray *) font->tf_CharLoc;    // Pointer to each characters specific data
  462.  
  463.     textchar = 0;    // Start at first encoded character in bitmap
  464.  
  465.     while (textchar + fd->lowchar <= fd->hichar)
  466.     {
  467.         fd->charoffset = farray->CharIndex[textchar].offset;
  468.         fd->charwidth =  farray->CharIndex[textchar].size;
  469.  
  470.         // Do nothing if this char cannot be modified!
  471.         if ( (short) fd->charwidth > (short) 2)
  472.             ModifyCharacter( fd);
  473.         textchar ++;
  474.     }
  475.  
  476.     // Release it - since we don't need it anymore
  477.     FreeMem( fd, sizeof (struct FontDescription));
  478.  
  479.     ctsfont->tf_Accessors = 1;
  480.  
  481.     return ctsfont;
  482. }
  483.  
  484. struct TextFont *CreateCatharsisFontA( REG(a0,struct TextFont *font))
  485. {
  486.     return CreateCatharsisFont( font);
  487. }
  488.  
  489. /* ------------------------------------------------------------------------------------- */
  490.  
  491. struct TextFont *OpenCatharsisFont( struct TextFont *font, REG(a6, struct SharedLib *base))
  492. {
  493.     struct TextFont *found;
  494.     ULONG i, emptyPtr;
  495.  
  496.     found = NULL;
  497.     emptyPtr = -1L;
  498.     i = 0;
  499.  
  500.     // Scan through list of remembered TextFonts to find the matching one
  501.     while (i < 256 && !found)
  502.     {
  503.         if ( !base->sl_TextFont[i])    // Empty entry?
  504.         {
  505.             if (emptyPtr == -1L)    // No empty pointer remembered?
  506.                 emptyPtr = i;        // Remember first empty pointer
  507.             i ++;                    // Next
  508.         }
  509.         else    // It's non-empty
  510.         {
  511.             if (font == base->sl_TextFont[i])
  512.             {
  513.                 found = base->sl_CatharsisFont[i];
  514.                 found->tf_Accessors ++;
  515.             }
  516.             else
  517.             {
  518.                 i ++;    // Skip to next
  519.             }
  520.         }
  521.     }
  522.  
  523.     // If this font is new, check also if there is a free entry useable
  524.     if (!found && emptyPtr != -1L)
  525.     {
  526.         found = CreateCatharsisFont( font);
  527.         if (found)
  528.         {
  529.             base->sl_TextFont[emptyPtr] = font;
  530.             base->sl_CatharsisFont[emptyPtr] = found;
  531.         }
  532.     }
  533.  
  534.     return found;
  535. }
  536.  
  537. struct TextFont *OpenCatharsisFontA( REG(a0, struct TextFont *font), REG(a6, struct SharedLib *base))
  538. {
  539.     return OpenCatharsisFont( font, base);
  540. }
  541.  
  542. /* ---------------------------------------------------------------------------------- */
  543.  
  544. void CloseCatharsisFont( struct TextFont *font, REG(a6, struct SharedLib *base))
  545. {
  546.     ULONG i, found;
  547.  
  548.     font->tf_Accessors --;
  549.  
  550.     found = -1L;
  551.  
  552.     // Can we remove it?
  553.     if ( (short) font->tf_Accessors < (short) 1)
  554.     {
  555.         i = 0;
  556.         while (i < 256 && found == -1L)
  557.         {
  558.             if (font == base->sl_CatharsisFont[i])
  559.                 found = i;
  560.             i ++;
  561.         }
  562.  
  563.         if (found != -1L)
  564.         {
  565.             FreeMem( font->tf_CharData, font->tf_Modulo * font->tf_YSize);
  566.             FreeMem( font, sizeof (struct TextFont));
  567.             base->sl_TextFont[found] = NULL;
  568.             base->sl_CatharsisFont[found] = NULL;
  569.         }
  570.     }
  571. }
  572.  
  573. void CloseCatharsisFontA( REG(a0, struct TextFont *font), REG(a6, struct SharedLib *base))
  574. {
  575.     CloseCatharsisFont( font, base);
  576. }
  577.  
  578. /*    -------------------------------------------------------------------------------------------------
  579.     Compute for a colour value its corresponding catharsis value.
  580.     Example:
  581.         red bg colour = 27, green bg colour = 56, blue bg colour = 31
  582.         red fg colour = 00, green fg colour = 37, blue fg colour = 08
  583.         normal = set it to TRUE if background is lighter than foreground, otherwise set it to FALSE
  584.     r = ComputeValue( 27, 00, 1);
  585.     g = ComputeValue( 56, 37, 1);
  586.     b = ComputeValue( 31, 08, 1);
  587.  
  588. */
  589.  
  590. int ComputeCatharsisValue( int bg, int fg, int percent, int normal)
  591. {
  592.     int dist, retval;
  593.  
  594.     if (bg > fg)
  595.         dist = bg - fg;
  596.     else
  597.         dist = fg - bg;
  598.  
  599.     // If distance is greater than halve of maximum luminance, darken or lighten pen-luminance
  600.     if (percent >= 50)
  601.     {
  602.         if (normal)                    // Background is lighter than foreground
  603.         {
  604.             if (bg - 23 >= 0)
  605.                 retval = bg - 23;    // Darken background by 'n' (here: 3 * bitspergun - 1)
  606.             else
  607.                 retval = 0;            // Minimum possible
  608.         }
  609.         else                        // Foreground lighter than background
  610.         {
  611.             if (fg > bg)
  612.                 retval = fg - (dist / 2);
  613.             else
  614.                 retval = fg;
  615.         }
  616.     }
  617.     else                // Interpol. of values
  618.     {
  619.         if (normal)
  620.         {
  621.             retval = (fg * (percent / 2)) / 100;
  622.         }
  623.         else
  624.         {
  625.             retval = (bg * (percent / 2)) / 100;
  626.         }
  627.     }
  628.  
  629.     if (retval < 0)
  630.         retval = 0;
  631.     if (retval > 255)
  632.         retval = 255;
  633.  
  634.     return retval;
  635. }
  636.  
  637. int ComputeCatharsisValueA( REG(d0, int bg), REG(d1, int fg), REG(d2, int percent), REG(d3, int normal))
  638. {
  639.     return ComputeCatharsisValue( bg, fg, percent, normal);
  640. }
  641.  
  642. /* ---------------------------------------------------------------------------------- */
  643.  
  644. ULONG CompressColorValue( ULONG r, ULONG g, ULONG b)
  645. {
  646.     ULONG val;
  647.  
  648.     val =  (r & 0xFF000000L) >> 8;
  649.     val |= (g & 0xFF000000L) >> 16;
  650.     val |= (b & 0xFF000000L) >> 24;
  651.  
  652.     return val;
  653. }
  654.  
  655. ULONG CompressColorValueA( REG(d0, ULONG r), REG(d1, ULONG g), REG(d2, ULONG b))
  656. {
  657.     return CompressColorValue( r, g, b);
  658. }
  659.  
  660. /*    -------------------------------------------------------------------------------------------------
  661.     Convert  a  8-bit  colour  value  into a AmigaOS compatible 32bit one: e.g. v = 139 (0x8B) - 8bit
  662.     result:    v = 0x8BBBBBBB - 32bit
  663. */
  664.  
  665. ULONG CompatibleColorValue( ULONG v)
  666. {
  667.     ULONG help, nibble;
  668.  
  669.     nibble = help = (v & 0xF);                // 4bit
  670.     nibble = help = (help << 4) | nibble;    // 8 bit (byte)
  671.     help = (help << 8) | nibble;            // 16 bit (word)
  672.     help = (help << 8) | nibble;            // 24 bit
  673.  
  674.     v = (v << 24);
  675.     v |= help;        // longword
  676.     return v;
  677. }
  678.  
  679. ULONG CompatibleColorValueA( REG(d0, ULONG v))
  680. {
  681.     return CompatibleColorValue( v);
  682. }
  683.  
  684. /*    -------------------------------------------------------------------------------------------------
  685.     Compute a new colour-value basing on two that you passed in to this function.
  686.  
  687.     val1:    background  colour  value,  32bit,  where  the  leftmost  8  bits  will be ignore by this
  688.             function since it is normally used as alpha channel:
  689.  
  690.             aaRRGGBB:    aa  -  8  bit alpha, RR - 8 bit red component, GG - 8 bit green component and
  691.                         BB - 8 bit blue component
  692.  
  693.     val2:    same as val1 but for foreground colour
  694.     red:    pointer  to  a long-word variable to store a AmigaOS 32bit red component value, i.e. 8bit
  695.             (RR)  0x8B  would  be  expanded  to  0x8BBBBBBB  ready  to  use by OS 3 graphic functions
  696.             LoadRGB32(), FindColor() and so on.
  697.             'red' may be zero, then the red-value is not stored
  698.     green:    same as for red, but for the green component
  699.     blue:    same as for red, but for the blue component
  700.  
  701.     RESULTS:
  702.             Returns a compressed 32bit value, format aaRRGGBB in d0
  703.             If  red,  green,  blue are non-zero, into the supplied variables the OS compatible colour
  704.             values will be dropped
  705.  
  706. */
  707.  
  708. ULONG CatharsisColorValue( ULONG val1, ULONG val2, ULONG *red, ULONG *green, ULONG *blue)
  709. {
  710.     ULONG val3, val4, bg[3], fg[3], r, g, b;
  711.  
  712.     bg[0] = ((val1 & 0xFF0000L) >> 16);    // Get red
  713.     bg[1] = ((val1 & 0xFF00L) >> 8);    // Get green
  714.     bg[2] = (val1 & 0xFFL);                // Get blue
  715.  
  716.     fg[0] = ((val2 & 0xFF0000L) >> 16);    // Get red
  717.     fg[1] = ((val2 & 0xFF00L) >> 8);    // Get green
  718.     fg[2] = (val2 & 0xFFL);                // Get blue
  719.  
  720.  
  721.     /* Figure out if which is lighter (background or foreground) */
  722.     val1 = ((bg[0] * 30) + (bg[1] * 59) + (bg[2] * 11)) / 100;
  723.     val2 = ((fg[0] * 30) + (fg[1] * 59) + (fg[2] * 11)) / 100;
  724.  
  725.     if (val1 > val2)
  726.     {
  727.         val3 = TRUE;        // Normal display, background lighter than foreground
  728.         val4 = val1 - val2;    // How much in per cent is the background lighter
  729.     }
  730.     else
  731.     {
  732.         val3 = FALSE;
  733.         val4 = val2 - val1;    // How much in per cent is the foreground lighter
  734.     }
  735.  
  736.     r = ComputeCatharsisValue( bg[0], fg[0], val4, val3);
  737.     g = ComputeCatharsisValue( bg[1], fg[1], val4, val3);
  738.     b = ComputeCatharsisValue( bg[2], fg[2], val4, val3);
  739.  
  740.     val3 = r;
  741.     val3 = (val3 << 8);
  742.     val3 |= g;
  743.     val3 = (val3 << 8);
  744.     val3 |= b;
  745.  
  746.     r = CompatibleColorValue( r);
  747.     g = CompatibleColorValue( g);
  748.     b = CompatibleColorValue( b);
  749.  
  750.     if (red)
  751.         *red = r;
  752.     if (green)
  753.         *green = g;
  754.     if (blue)
  755.         *blue = b;
  756.  
  757.     return val3;
  758. }
  759.  
  760. ULONG CatharsisColorValueA( REG(d0, ULONG val1), REG(d1, ULONG val2), REG(a0, ULONG *red), REG(a1, ULONG *green), REG(a2, ULONG *blue))
  761. {
  762.     return CatharsisColorValue( val1, val2, red, green, blue);
  763. }
  764.  
  765. /* ------------------------------------------------------------------------------------------ */
  766.  
  767. void CatharsisText( struct RastPort *rp, unsigned char *str, unsigned int len, unsigned int pen, struct TextFont *ctsfont)
  768. {
  769.     unsigned short x, y, p;
  770.     struct TextFont *f;
  771.  
  772.     x = rp->cp_x;
  773.     y = rp->cp_y;
  774.     p = rp->FgPen;
  775.     f = rp->Font;
  776.  
  777.     Text( rp, str, len);
  778.  
  779.     if (ctsfont)
  780.     {
  781.         SetDrMd( rp, JAM1);
  782.         SetFont( rp, ctsfont);
  783.         Move( rp, x, y);
  784.         SetAPen( rp, pen);
  785.         Text( rp, str, len);
  786.         SetFont( rp, f);
  787.         SetAPen( rp, p);
  788.     }
  789. }
  790.  
  791. void CatharsisTextA( REG(a1,struct RastPort *rp), REG(a0,unsigned char *str), REG(d0,unsigned int len), REG(d1,unsigned int pen), REG(a2, struct TextFont *font))
  792. {
  793.     CatharsisText( rp, str, len, pen, font);
  794. }
  795.  
  796. /* ---------------------------------------------------------------------------------- */
  797.